/*
 * Photobucket.com service implementation
 */

package imageuploader.core;

import java.io.*;
import java.util.HashMap;
import java.util.Properties;

import org.apache.commons.httpclient.*;
import org.apache.commons.httpclient.cookie.CookiePolicy;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.multipart.*;

import org.htmlparser.*;
import org.htmlparser.filters.CssSelectorNodeFilter;
import org.htmlparser.util.*;
/**
 *
 * @author nir
 */
public class PhotoBucketService extends BaseImageHostingServiceImpl{
        
    public PhotoBucketService(Properties props){
        super(props);
    }
    
    @Override
    protected String getUploadPath() {
        String $album = this.album.replaceAll(" ", "%20");
        return new StringBuilder(uploadBasePath).append($album).append("/").toString();
    }
    
    @Override
    protected String getCreateAlbumURL(){
        return getUploadPath();
    }

    @Override
    public void setAlbum(String album){

            this.album = album;
        
    }    
    
    public void login(String usernameOrEmail, String password) throws ImageUploaderException {
        NameValuePair[] query = {
            new NameValuePair("action", "login"),
            new NameValuePair("redir", ""),
            new NameValuePair("redirectAction", ""),
            new NameValuePair("returnUrl", ""),
            new NameValuePair("remember", "true"),
            new NameValuePair("login", "Login"),
            new NameValuePair("usernameemail", usernameOrEmail),
            new NameValuePair("password", password)
        };
        
        HttpClient client = new HttpClient();
        client.getParams().setCookiePolicy(CookiePolicy.BROWSER_COMPATIBILITY);
        PostMethod post = new PostMethod(this.loginURL);

        post.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
        post.addParameters(query);
        Parser htmlParser = new Parser();
        NodeList nl = null;
        ImageUploaderException exceptionToThrow = null;
        try{
            client.executeMethod(post);
        }catch(Exception e){
            exceptionToThrow = new ImageUploaderException(e);
        }
        
        if(exceptionToThrow==null){
            if(post.getStatusCode()==200){
                try{
                    BufferedReader reader = new BufferedReader(new InputStreamReader(post.getResponseBodyAsStream()));
                    StringBuilder html = new StringBuilder();
                    String line = null;
                    while((line=reader.readLine())!=null){
                        html.append(line).append("\n");
                    }
                    htmlParser.setInputHTML(html.toString());
                    nl = htmlParser.parse(new CssSelectorNodeFilter("div#panelLoginError>h1"));
                }catch(Exception e){
                    exceptionToThrow = new ImageUploaderException(e);
                }

                if(nl!=null && nl.size()>0){
                    String error = nl.elementAt(0).getText();
                    if(!error.isEmpty()){
                        exceptionToThrow = new ImageUploaderException(error);
                    }
                }else{
                    exceptionToThrow = new ImageUploaderException("Unknown error");
                }
            }else{
                try{
                    this.uploadBasePath = post.getResponseHeader("location").getValue();
                    this.cookies = client.getState().getCookies();
                }catch(Exception e){
                    exceptionToThrow = new ImageUploaderException(e);
                }
            }
        }
        post.releaseConnection();
        if(exceptionToThrow!=null){
            throw exceptionToThrow;
        }
    }

    public void upload(File[] files) throws ImageUploaderException{
        HttpClient client = getHttpClient();
        String path = getUploadPath();
        
        System.out.println(path);
        
        StringPart action = new StringPart("action", "uploadimage"),
                desc = new StringPart("image_desc", "");
        PostMethod completePost = new PostMethod(path);
        NameValuePair[] query = {
            new NameValuePair("action", "completeupload"),
            new NameValuePair("media", "image"),
            new NameValuePair("listValidVideoFiles", "3g2,3gp,3gp2,3gpp,3p,asf,avi,divx,dv,dvx,flv,gif,moov,mov,mp4,mpeg4,mpg4,mpe,mpeg,mpg,qt,swf,wmv,xvid,rm"),
            new NameValuePair("listValidImageFiles", "gif,jpg,jpeg,png,bmp,swf")
        };  
        completePost.addParameters(query);
        completePost.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");        
        
        PostMethod current = null;
        numOfFiles = files.length;
        try{ 
            // Uploading files
            for(int i=0;i<files.length;i++){

                current = getPostMethod(path);
                Part[] parts = {
                 action,
                 desc,
                 new FilePart("the_image", files[i])
                };
                current.setRequestEntity(
                    new MultipartRequestEntity(parts, current.getParams())
                );
                client.executeMethod(current);
                current.releaseConnection();
                
                numOfFiles-=1;
                events.dispatchEvent("fileUploaded");
                
                
            }
            current = null;
            // Complete the uploading

            client.executeMethod(completePost);
            
            completePost.releaseConnection();
            
            events.dispatchEvent("finishUpload");
            
        }catch(Exception e){
            throw new ImageUploaderException(e);
        }finally{
            if(current!=null){
                current.releaseConnection();
            }else{
                completePost.releaseConnection();
            }            
            numOfFiles = 0;
        }         
        
       
    }

    public void createAlbum(String album) throws ImageUploaderException{
        
        NameValuePair[] query = {
            new NameValuePair("action", "addalbum"),
            new NameValuePair("redirect", "new"),
            new NameValuePair("album", album)
        };
        HttpClient client = getHttpClient();
        PostMethod post = new PostMethod(getCreateAlbumURL());

        post.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
        post.addParameters(query);
        Parser htmlParser = new Parser();
        NodeList nl = null;
        ImageUploaderException exceptionToThrow = null;
        try{
            client.executeMethod(post);
        }catch(Exception e){
            exceptionToThrow = new ImageUploaderException(e);
        }
        
        if(exceptionToThrow==null){
            if(post.getStatusCode()==200){
                try{
                    htmlParser.setInputHTML(post.getResponseBodyAsString());
                    nl = htmlParser.parse(new CssSelectorNodeFilter("h1#panelErrorMessage"));
                }catch(Exception e){
                    exceptionToThrow = new ImageUploaderException(e);
                }

                if(nl!=null && nl.size()>0){
                    String error = nl.elementAt(0).getText();
                    if(!error.isEmpty()){
                        exceptionToThrow = new ImageUploaderException(error);
                    }else{
                        exceptionToThrow = new ImageUploaderException("Unknown Error");
                    }
                }else{
                    exceptionToThrow = new ImageUploaderException("Unknown Error");
                }
            }else{
                setAlbum(album);
            }
        }
        post.releaseConnection();
        if(exceptionToThrow!=null) throw exceptionToThrow;
        
    }
    
    protected HttpClient getHttpClient(){

        HttpClient client = new HttpClient();

        //Create a new HttpState container
        HttpState initialState = new HttpState();
        initialState.addCookies(this.cookies);
        //set the HttpState for the client
        client.setState(initialState);
        
        return client;
    }
    
    protected PostMethod getPostMethod(String url){
        PostMethod post = new PostMethod(url);
        post.setRequestHeader("User-Agent", "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.12) Gecko/20080207 Ubuntu/7.10 (gutsy) Firefox/2.0.0.12");
        post.setRequestHeader("Accept", "text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5");
        post.setRequestHeader("Accept-Language", "en-us,en;q=0.5");
        post.setRequestHeader("Accept-Charset", "ISO-8859-1,utf-8;q=0.7,*;q=0.7");
        post.setRequestHeader("Keep-Alive", "300");
        post.setRequestHeader("Connection", "keep-alive");
        return post;
    }

    public HashMap<String, String> getAlbumList() throws ImageUploaderException {
        HashMap<String, String> albums = new HashMap<String, String>();
        HttpClient client = getHttpClient();
        GetMethod get = new GetMethod(getUploadPath());
        ImageUploaderException exceptiontoThrow = null;
        Parser parser = new Parser();
        NodeList nl = null;
        try{
            client.executeMethod(get);
        }catch(Exception ex){
            exceptiontoThrow = new ImageUploaderException(ex);
        }
        if(exceptiontoThrow==null){
            try{
                BufferedReader reader = new BufferedReader(new InputStreamReader(get.getResponseBodyAsStream()));
                StringBuilder html = new StringBuilder();
                String line = null;
                while((line=reader.readLine())!=null){
                    html.append(line).append("\n");
                }
                parser.setInputHTML(html.toString());
                nl = parser.parse(new CssSelectorNodeFilter("ul#albumList li a"));
            }catch(Exception ex){
                exceptiontoThrow = new ImageUploaderException(ex);
            }
            
            if(nl!=null){
                if(nl.size()>0){
                    String tmpAlbum;
                    for(int i=0;i<nl.size();i++){
                        tmpAlbum = nl.elementAt(i).getFirstChild().getText().trim();
                        albums.put(tmpAlbum,tmpAlbum);
                    }
                }
            }else{
                exceptiontoThrow = new ImageUploaderException("Unknown Exception");
            }
            
        }
        
        if(exceptiontoThrow!=null){
            throw exceptiontoThrow;
        }else{
            return albums;
        }
    }

    public int getUploadLength() {
        return numOfFiles;
    }

}
